package com.goldsprite.ruletilemap.core;

import java.util.*;
import java.util.stream.Collectors;

public class RegularizationHandler {
    private final Map<String, RuleTile> ruleTiles = new LinkedHashMap<>();
    private final Random random = new Random();

    public void registerRuleTile(RuleTile ruleTile) {
        ruleTiles.put(ruleTile.getGid(), ruleTile);
    }

    public String processMap(String mapData) {
        String[] rows = mapData.trim().split("\n");
        int height = rows.length;
        int width = rows[0].trim().split(" +").length;

        String[][] grid = parseMapToGrid(rows, width, height);
        String[][] resultGrid = new String[height][width];

        // 复制原始网格
        for (int y = 0; y < height; y++) {
            System.arraycopy(grid[y], 0, resultGrid[y], 0, width);
        }

        // 从左到右，从下到上扫描
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                String currentId = grid[y][x];
                if (currentId.startsWith("g")) {
                    String resolvedId = resolveTile(grid, x, y, width, height, currentId);
                    resultGrid[y][x] = resolvedId;
                }
            }
        }

        return convertGridToString(resultGrid);
    }

    private String resolveTile(String[][] grid, int x, int y, int width, int height, String gid) {
        RuleTile ruleTile = ruleTiles.get(gid);
        if (ruleTile == null) return "0";

        List<String> neighbors = getMooreNeighbors(grid, x, y, width, height);
        List<RuleTile.RuleEntry> matchingRules = new ArrayList<>();

        for (RuleTile.RuleEntry rule : ruleTile.getNeighborRules()) {
            if (matchesRule(neighbors, rule.getCondition(), ruleTile.getAttentionList())) {
                matchingRules.add(rule);
            }
        }

        if (matchingRules.isEmpty()) {
            return "0";
        }

        if(matchingRules.size() == 1){
            return matchingRules.get(0).getTargetId();
        }

        // 按优先级排序（y和n的数量之和，数值越大优先级越高）
        matchingRules.sort((rule1, rule2) -> {
            int priority1 = ruleTile.getRulePriorities().get(rule1);
            int priority2 = ruleTile.getRulePriorities().get(rule2);
            return Integer.compare(priority2, priority1); // 降序排列
        });

        // 从最高优先级的规则中随机选择一个
        int maxPriority = ruleTile.getRulePriorities().get(matchingRules.get(0));
        List<RuleTile.RuleEntry> topPriorityRules = matchingRules.stream()
                .filter(rule -> ruleTile.getRulePriorities().get(rule) == maxPriority)
                .collect(Collectors.toList());

        return topPriorityRules.get(random.nextInt(topPriorityRules.size())).getTargetId();
    }

    private List<String> getMooreNeighbors(String[][] grid, int x, int y, int width, int height) {
        // Moore邻域顺序: 左上, 上, 右上, 左, 右, 左下, 下, 右下
        int[] dx = {-1, 0, 1, -1, 1, -1, 0, 1};
        int[] dy = {1, 1, 1, 0, 0, -1, -1, -1};

        List<String> neighbors = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            neighbors.add(getNeighborId(grid, nx, ny, width, height));
        }
        return neighbors;
    }

    private String getNeighborId(String[][] grid, int x, int y, int width, int height) {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return "0"; // 边界外视为空气
        }
        return grid[y][x];
    }

    private boolean matchesRule(List<String> neighbors, String rule, Set<String> attentionList) {
        if (rule.length() != 9) return false;
        String matchRule = rule.replaceFirst("o", "");

        for (int i = 0; i < 8; i++) {
            char condition = matchRule.charAt(i);
            String neighbor = neighbors.get(i);

            switch (condition) {
                case 'y':
                    if (!attentionList.contains(neighbor)) return false;
                    break;
                case 'n':
                    if (!neighbor.equals("0")) return false;
                    break;
                case '?':
                case 'o':
                    // 任意值或自身都通过
                    break;
                default:
                    return false;
            }
        }
        return true;
    }

    private String[][] parseMapToGrid(String[] rows, int width, int height) {
        String[][] grid = new String[height][width];
        for (int y = 0; y < height; y++) {
            String[] cells = rows[height - 1 - y].trim().split(" +"); // 反转Y轴
            for (int x = 0; x < width; x++) {
                grid[y][x] = cells[x];
            }
        }
        return grid;
    }

    private String convertGridToString(String[][] grid) {
        StringBuilder sb = new StringBuilder();
        for (int y = grid.length - 1; y >= 0; y--) { // 反转Y轴输出
            for (int x = 0; x < grid[y].length; x++) {
                sb.append(grid[y][x]);
                if (x < grid[y].length - 1) sb.append(" ");
            }
            if (y > 0) sb.append("\n");
        }
        return sb.toString();
    }
}
